#include "l4_packet.h"
#include "decode/IPv4Layer.h"
#include "server/server.h"

namespace secsmart_tcpip
{

void L4PacketHandler::register_tcp_conn_event_cb(tcp_conn_event_cb_t cb, void *user_data)
{
    if (m_tcp_handler != nullptr) {
        return m_tcp_handler->register_tcp_conn_event_cb(cb, user_data);
    }
}

void L4PacketHandler::init()
{
    m_tcp_handler = new TcpPacketHandler;
    m_enable_filter_packet = false;
}

void L4PacketHandler::uninit()
{
    if (m_tcp_handler != nullptr) {
        delete m_tcp_handler;
        m_tcp_handler = nullptr;
    }
}

uint32_t L4PacketHandler::process_packet(uint8_t *in_pkt, packet_meta_t *meta)
{
    if (in_pkt == NULL || meta == NULL) {
        return L4_PKT_ERR;
    }
    m_stat.stat_rcv_pkt(meta->pkt_len);

    // 报文过滤
    if (m_enable_filter_packet && filter_packet(meta)) {
        m_stat.stat_drop_pkt(L4_PKT_FILTER);
        return L4_PKT_FILTER;
    }

    // 报文处理,只处理tcp/udp报文
    uint32_t ret = L4_PKT_ERR;
    if (meta->ip_protocol == PACKETPP_IPPROTO_TCP) {
        ret = process_tcp_packet(in_pkt, meta);
    } else if (meta->ip_protocol == PACKETPP_IPPROTO_UDP) {
        ret = process_udp_packet(in_pkt, meta);
    }

    if (ret == L4_PKT_CACHED) {
        m_stat.stat_cache_pkt();
        return L4_PKT_OK;
    }

    if (ret != L4_PKT_OK) {
        m_stat.stat_drop_pkt(ret);
        return L4_PKT_ERR;
    }
    m_stat.stat_snd_pkt(meta->l4_payload_len);
    return L4_PKT_OK;
}

bool L4PacketHandler::filter_packet(packet_meta_t *meta)
{
    shared_ptr<Server> server = ServerManager::get_instance().get_server(meta->sip, meta->sport, meta->ip_protocol);
    if (server != NULL) {
        meta->direction = PKT_DIRECTION_SERVER_TO_CLIENT;
        meta->hit_server = 1;
        return server->ip_filter.filter_ip(meta->dip);
    }

    server = ServerManager::get_instance().get_server(meta->dip, meta->dport, meta->ip_protocol);
    if (server != NULL) {
        meta->direction = PKT_DIRECTION_CLIENT_TO_SERVER;
        meta->hit_server = 1;
        return server->ip_filter.filter_ip(meta->sip);
    }

    // 没有命中server，报文过滤掉
    return true;
}

uint32_t L4PacketHandler::process_tcp_packet(uint8_t *pkt, packet_meta_t *meta)
{
    if (m_tcp_handler == nullptr) {
        return L4_PKT_ERR;
    }
    uint32_t ret = m_tcp_handler->process_packet(pkt, meta);
    if (ret == TcpPacketHandler::TCP_PKT_CACHE) {
        return L4_PKT_CACHED;
    } else if(ret != TcpPacketHandler::TCP_PKT_OK) {
        return L4_PKT_ERR;
    }
    return L4_PKT_OK;
}

uint32_t L4PacketHandler::process_udp_packet(uint8_t *pkt, packet_meta_t *meta)
{
    (void)pkt;
    (void)meta;
    return L4_PKT_OK;
}

}
